package org.apereo.cas.config;
import com.google.common.base.Throwables;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.http.client.AuthCache;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apereo.cas.adaptors.rest.RestAuthenticationApi;
import org.apereo.cas.adaptors.rest.RestAuthenticationHandler;
import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
import org.apereo.cas.authentication.AuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalResolver;
import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.model.support.rest.RestAuthenticationProperties;
import org.apereo.cas.configuration.support.Beans;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
/**
* This is {@link CasRestAuthenticationConfiguration}.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
@Configuration("casRestAuthenticationConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CasRestAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer {
@Autowired
@Qualifier("personDirectoryPrincipalResolver")
private PrincipalResolver personDirectoryPrincipalResolver;
@Autowired
private CasConfigurationProperties casProperties;
@Bean
@RefreshScope
public RestTemplate restAuthenticationTemplate() {
try {
final URI casHost = new URI(casProperties.getServer().getName());
final HttpHost host = new HttpHost(casHost.getHost(), casHost.getPort(), casHost.getScheme());
final ClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactoryBasicAuth(host);
return new RestTemplate(factory);
} catch (final Exception e) {
throw Throwables.propagate(e);
}
}
@ConditionalOnMissingBean(name = "restAuthenticationApi")
@Bean
@RefreshScope
public RestAuthenticationApi restAuthenticationApi() {
return new RestAuthenticationApi(restAuthenticationTemplate(), casProperties.getAuthn().getRest().getUri());
}
@Bean
@RefreshScope
public AuthenticationHandler restAuthenticationHandler() {
final RestAuthenticationProperties rest = casProperties.getAuthn().getRest();
final RestAuthenticationHandler r = new RestAuthenticationHandler(rest.getName(), restAuthenticationApi());
r.setPasswordEncoder(Beans.newPasswordEncoder(rest.getPasswordEncoder()));
return r;
}
@Override
public void configureAuthenticationExecutionPlan(final AuthenticationEventExecutionPlan plan) {
if (StringUtils.isNotBlank(casProperties.getAuthn().getRest().getUri())) {
plan.registerAuthenticationHandlerWithPrincipalResolver(restAuthenticationHandler(), personDirectoryPrincipalResolver);
}
}
private static class HttpComponentsClientHttpRequestFactoryBasicAuth extends HttpComponentsClientHttpRequestFactory {
private final HttpHost host;
/**
* Instantiates a new Http components client http request factory basic auth.
*
* @param host the host
*/
HttpComponentsClientHttpRequestFactoryBasicAuth(final HttpHost host) {
super();
this.host = host;
}
@Override
protected HttpContext createHttpContext(final HttpMethod httpMethod, final URI uri) {
return createHttpContext();
}
private HttpContext createHttpContext() {
final AuthCache authCache = new BasicAuthCache();
final BasicScheme basicAuth = new BasicScheme();
authCache.put(host, basicAuth);
final BasicHttpContext localcontext = new BasicHttpContext();
localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
return localcontext;
}
}
}